﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Media.Imaging;
using MediaPlayer.VideoCore;
using System.Threading;

namespace MediaPlayer {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public CameraInfos Info {
            get;
            private set;
        }

        private double m_speedRate = 0;
        private object m_looker = new object();
        public MainWindow() {
            InitializeComponent();
            Info = XmlHelper.GetCameras(Constants.ConfigPath);
            DataContext = Info;
            
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) {

        }

        /// <summary>
        /// Plays the speed changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="prochanged">The <see cref="System.Windows.RoutedPropertyChangedEventArgs&lt;System.Object&gt;"/> instance containing the event data.</param>
        private void PlaySpeedChanged(object sender, RoutedPropertyChangedEventArgs<object> prochanged) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null) {
                lock (m_looker) {
                    item.SpeedRate = (int)m_playSpeed.Value.Value;
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the btnPause control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void btnPause_Click(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null) {
                item.IsPlaying = false;
            }
        }
        /// <summary>
        /// Called when [connect].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnConnect(object sender, RoutedEventArgs e) {
            try {
                VideoCoreClient client = new VideoCoreClient();
                MessageBox.Show(client.Welcome());
                Info.WcfUrl = string.Empty;
            } catch (Exception ex) {
                MessageBox.Show("Cant connect Server!");
            }
        }

        /// <summary>
        /// Called when [add new camera].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnAddNewCamera(object sender, RoutedEventArgs e) {
            CameraInfo camera = new CameraInfo() {
                IP = m_tbCamIP.Text,
                Username = m_tbUsername.Text,
                Password = m_pbPassword.Password
            };

            Info.Cameras.Add(camera);
            XmlHelper.SaveCameraConfigs(Constants.ConfigPath, Info);
        }
        /// <summary>
        /// Called when [play].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnPlay(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;

            if (item != null) {
                item.IsPlaying = true;
                item.SpeedRate = (int)m_playSpeed.Value.Value;
                if (!item.IsInitial) {
                    item.IsInitial = true;
                    ThreadPool.QueueUserWorkItem(Play, item);
                }
            }
        }

        /// <summary>
        /// Plays the specified state.
        /// </summary>
        /// <param name="state">The state.</param>
        private void Play(object state) {
            CameraInfo info = state as CameraInfo;
            if (info != null) {
                VideoCoreClient client = new VideoCoreClient();
                VideoFileInfo lastFile = client.GetDateAt(info.IP, info.RequestTime);//client.GetLastFile(info.IP);
                int ignoreFrame = 1;
                info.MaxFrame = lastFile.FrameLength;
                info.StartTime = lastFile.StartTime.ToString();
                info.EndTime = lastFile.EndTime.ToString();
                while (info.CurrentFrame < lastFile.FrameLength) {
                    // If Speed Rate is larger than 6
                    // We should get the Speed/2 frame
                    // And get frame faster than 2 time
                    ignoreFrame = info.SpeedRate > 6 ? info.SpeedRate / 2 : info.SpeedRate;
                    if (info.IsPlaying) {
                        info.CurrentFrame += ignoreFrame;
                        byte[] image = client.GetVideoStream(lastFile.Name, Math.Min(info.CurrentFrame, lastFile.FrameLength - 1));
                        m_image1.Dispatcher.BeginInvoke((Action)delegate {
                            m_image1.Source = BitmapFrame.Create(new MemoryStream(image));
                        });
                    } else {
                        if (info.IsBackFrame) {
                            info.IsBackFrame = false;
                            byte[] image = client.GetVideoStream(lastFile.Name, Math.Max(info.CurrentFrame -= ignoreFrame, 0));
                            m_image1.Dispatcher.BeginInvoke((Action)delegate {
                                m_image1.Source = BitmapFrame.Create(new MemoryStream(image));
                                m_image2.Source = BitmapFrame.Create(new MemoryStream(image));
                            });
                        } else if (info.IsNextFrame) {
                            info.IsNextFrame = false;
                            byte[] image = client.GetVideoStream(lastFile.Name, Math.Min(info.CurrentFrame += ignoreFrame, lastFile.FrameLength - 1));
                            m_image1.Dispatcher.BeginInvoke((Action)delegate {
                                m_image1.Source = BitmapFrame.Create(new MemoryStream(image));
                            });
                        }
                    }
                    Thread.Sleep(TimeSpan.FromMilliseconds(info.SpeedRate > 6 ?
                        (lastFile.Durations / 2) : lastFile.Durations));
                    if (info.CurrentFrame >= lastFile.FrameLength){
                        lastFile = client.GetNextFile(info.IP, lastFile.Name);//client.GetLastFile(info.IP);
                        info.MaxFrame = lastFile.FrameLength;
                        info.StartTime = lastFile.StartTime.ToString();
                        info.EndTime = lastFile.EndTime.ToString();
                        info.CurrentFrame = 0;
                    }
                }
                //info.IsInitial = false;
                //info.IsPlaying = false;
            }
        }

        /// <summary>
        /// Called when [fast forward].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnFastForward(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null) {
                if (item.SpeedRate * 4 > 8) {
                    item.SpeedRate = 8;
                } else {
                    item.SpeedRate *= 4;
                }
            }
        }

        /// <summary>
        /// Called when [re wind].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnReWind(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null) {
                if (item.SpeedRate / 4 <= 1) {
                    item.SpeedRate = 1;
                } else {
                    item.SpeedRate /= 4;
                }
            }
        }

        /// <summary>
        /// Nexts the on frame.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void NextOneFrame(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null && !item.IsPlaying) {
                item.IsNextFrame = true;
            }
        }

        /// <summary>
        /// Backs the one frame.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void BackOneFrame(object sender, RoutedEventArgs e) {
            var item = dgCameraList.SelectedItem as CameraInfo;
            if (item != null && !item.IsPlaying) {
                item.IsBackFrame = true;
            }
        }
    }
}
